package com.masc.gurr.net;
/*
 *  Copyright (c) 2002-2003, The Joust Project
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without 
 *  modification, are permitted provided that the following conditions 
 *  are met:
 *
 *  - Redistributions of source code must retain the above copyright 
 *    notice, this list of conditions and the following disclaimer. 
 *  - Redistributions in binary form must reproduce the above copyright 
 *    notice, this list of conditions and the following disclaimer in 
 *    the documentation and/or other materials provided with the 
 *    distribution. 
 *  - Neither the name of the Joust Project nor the names of its 
 *    contributors may be used to endorse or promote products derived 
 *    from this software without specific prior written permission. 
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 *  File created by keith @ Mar 26, 2003
 *
 */



import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import net.kano.joscar.ByteBlock;
import net.kano.joscar.flap.FlapPacketEvent;
import net.kano.joscar.flapcmd.SnacCommand;
import net.kano.joscar.net.ClientConn;
import net.kano.joscar.net.ClientConnEvent;
import net.kano.joscar.net.ConnDescriptor;
import net.kano.joscar.snac.SnacPacketEvent;
import net.kano.joscar.snac.SnacResponseEvent;
import net.kano.joscar.snaccmd.CapabilityBlock;
import net.kano.joscar.snaccmd.CertificateInfo;
import net.kano.joscar.snaccmd.ExtraInfoBlock;
import net.kano.joscar.snaccmd.ExtraInfoData;
import net.kano.joscar.snaccmd.FullUserInfo;
import net.kano.joscar.snaccmd.InfoData;
import net.kano.joscar.snaccmd.ShortCapabilityBlock;
import net.kano.joscar.snaccmd.conn.MyInfoRequest;
import net.kano.joscar.snaccmd.conn.ServerReadyCmd;
import net.kano.joscar.snaccmd.conn.ServiceRedirect;
import net.kano.joscar.snaccmd.conn.SetEncryptionInfoCmd;
import net.kano.joscar.snaccmd.conn.YourInfoCmd;
import net.kano.joscar.snaccmd.icbm.ParamInfo;
import net.kano.joscar.snaccmd.icbm.ParamInfoCmd;
import net.kano.joscar.snaccmd.icbm.ParamInfoRequest;
import net.kano.joscar.snaccmd.icbm.RecvTypingNotification;
import net.kano.joscar.snaccmd.icbm.SendTypingNotification;
import net.kano.joscar.snaccmd.icbm.SetParamInfoCmd;
import net.kano.joscar.snaccmd.loc.LocRightsCmd;
import net.kano.joscar.snaccmd.loc.LocRightsRequest;
import net.kano.joscar.snaccmd.loc.SetInfoCmd;
import net.kano.joscar.snaccmd.loc.UserInfoCmd;
import net.kano.joscar.snaccmd.ssi.ActivateSsiCmd;
import net.kano.joscar.snaccmd.ssi.SsiDataCmd;
import net.kano.joscar.snaccmd.ssi.SsiDataRequest;
import net.kano.joscar.snaccmd.ssi.SsiItem;
import net.kano.joscar.snaccmd.ssi.SsiRightsCmd;
import net.kano.joscar.snaccmd.ssi.SsiRightsRequest;
import net.kano.joscar.ssiitem.BuddyItem;
import net.kano.joscar.ssiitem.DefaultSsiItemObjFactory;
import net.kano.joscar.ssiitem.GroupItem;
import net.kano.joscar.ssiitem.RootItem;
import net.kano.joscar.ssiitem.SsiItemObj;
import net.kano.joscar.ssiitem.SsiItemObjectFactory;

import android.widget.Toast;

import com.masc.gurr.Controller;
import com.masc.gurr.model.Contact;
import com.masc.gurr.model.ContactStatus;
import com.masc.gurr.model.Group;
import com.masc.gurr.model.ProtocolType;
import com.masc.gurr.model.xml.Reader;
import com.masc.gurr.view.activities.AccountActivity;

public class BosFlapConn extends BasicConn {

	private AccountActivity accountActivity = Controller.getInstance().getAccountActivity();
	private SsiItemObjectFactory itemFactory = new DefaultSsiItemObjFactory();

	private static final List<CapabilityBlock> MY_CAPS = Arrays.asList(
			CapabilityBlock.BLOCK_CHAT,
			CapabilityBlock.BLOCK_DIRECTIM,
			CapabilityBlock.BLOCK_FILE_GET,
			CapabilityBlock.BLOCK_FILE_SEND,
			CapabilityBlock.BLOCK_GAMES,
			CapabilityBlock.BLOCK_GAMES2,
			CapabilityBlock.BLOCK_ICON,
			CapabilityBlock.BLOCK_SENDBUDDYLIST,
			CapabilityBlock.BLOCK_TRILLIANCRYPT,
			CapabilityBlock.BLOCK_VOICE,
			CapabilityBlock.BLOCK_ADDINS,
			CapabilityBlock.BLOCK_ICQCOMPATIBLE,
			CapabilityBlock.BLOCK_SHORTCAPS,
			CapabilityBlock.BLOCK_ENCRYPTION,

			// ShortCapabilityBlock: f0 04 (unknown),
			// ShortCapabilityBlock: f0 05 (unknown),
			// ShortCapabilityBlock: 01 02 (unknown),
			// ShortCapabilityBlock: 01 03 (unknown),
			// ShortCapabilityBlock: f0 02 (unknown),
			// ShortCapabilityBlock: f0 03 (unknown),
			// 09 46 01 05 4c 7f 11 d1 82 22 44 45 45 53 54 00

			// Camera (no icon?)
			ShortCapabilityBlock.getCapFromShortBytes(0x01, 0x02),
			ShortCapabilityBlock.getCapFromShortBytes(0xf0, 0x02),

			// Microphone (dim icon)
			ShortCapabilityBlock.getCapFromShortBytes(0x01, 0x03),
			ShortCapabilityBlock.getCapFromShortBytes(0xf0, 0x03),
			// Conferencing (no icon)
			ShortCapabilityBlock.getCapFromShortBytes(0xf0, 0x04),

			// Conferencing available (makes icon not dim)
			ShortCapabilityBlock.getCapFromShortBytes(0xf0, 0x05),
			new CapabilityBlock(
					0x09, 0x46, 0x01, 0x05, 0x4c, 0x7f, 0x11, 0xd1,
					0x82, 0x22, 0x44, 0x45, 0x45, 0x53, 0x54, 0x00)

			//        CapabilityBlock.BLOCK_SOMETHING,
			);

	public BosFlapConn(ConnDescriptor cd, ICQ icq,
			ByteBlock cookie) {
		super(cd, icq, cookie);
	}

	protected void handleStateChange(final ClientConnEvent e) {

		System.out.println("icq: " + e.getOldState() + " -> " + e.getNewState() + ": " + e.getReason());

		Runnable run = new Runnable(){
			public void run(){

				/* update icq connection state in ICQ */
				Controller.getInstance().getIcq().setState(e.getNewState());

				if(e.getNewState().toString().equals("CONNECTED")){
					Toast.makeText(accountActivity.getApplicationContext(), "connected",
							Toast.LENGTH_SHORT).show();

					accountActivity.getBtIcqLogOut().setEnabled(true);
					
					/* if chatwindowactivity exist, enable textview+buttons */
					if (Controller.getInstance().getChatWindowActivity() != null) {
						Controller.getInstance().getChatWindowActivity().getOtrButton().setEnabled(true);
						Controller.getInstance().getChatWindowActivity().getChatInputET().setEnabled(true);
						Controller.getInstance().getChatWindowActivity().getSendButton().setEnabled(true);	
					}

					
				}
				else if(e.getNewState().toString().equals("NOT_CONNECTED")){
					accountActivity.getBtIcqLogOut().setEnabled(false);
					accountActivity.getBtIcqLogin().setEnabled(true); 
					Toast.makeText(accountActivity.getApplicationContext(), "disconnected",
							Toast.LENGTH_SHORT).show();	
					
					/* if chatwindowactivity exist, disable textview+buttons */
					if (Controller.getInstance().getChatWindowActivity() != null) {
						Controller.getInstance().getChatWindowActivity().getOtrButton().setEnabled(false);
						Controller.getInstance().getChatWindowActivity().getChatInputET().setEnabled(false);
						Controller.getInstance().getChatWindowActivity().getSendButton().setEnabled(false);	
					}
				}
				else {
					/* if chatwindowactivity exist, disable textview+buttons */
					if (Controller.getInstance().getChatWindowActivity() != null) {
						Controller.getInstance().getChatWindowActivity().getOtrButton().setEnabled(false);
						Controller.getInstance().getChatWindowActivity().getChatInputET().setEnabled(false);
						Controller.getInstance().getChatWindowActivity().getSendButton().setEnabled(false);	
					}
					accountActivity.getBtIcqLogin().setEnabled(false);
				}
			}
		};
		accountActivity.runOnUiThread(run);
	}

	protected void handleFlapPacket(FlapPacketEvent e) {
		super.handleFlapPacket(e);
	}

	protected void handleSnacPacket(SnacPacketEvent e) {
		super.handleSnacPacket(e);

		SnacCommand cmd = e.getSnacCommand();

		if (cmd instanceof ServerReadyCmd) {
			//            request(new SetIdleCmd(123456789));
			//            request(new SetExtraInfoCmd("I'm Available for chat!!!!"));
			request(new ParamInfoRequest());
			request(new LocRightsRequest());
			request(new SsiRightsRequest());
			request(new SsiDataRequest());

		} else if (cmd instanceof RecvTypingNotification) {
			RecvTypingNotification rtn = (RecvTypingNotification) cmd;

			request(new SendTypingNotification(rtn.getScreenname(),
					rtn.getTypingState()));
		}
	}

	protected void handleSnacResponse(SnacResponseEvent e) {
		super.handleSnacResponse(e);

		SnacCommand cmd = e.getSnacCommand();

		if (cmd instanceof LocRightsCmd) {

			request(new SetInfoCmd(new InfoData("yo", null, MY_CAPS, null)));
			request(new SetEncryptionInfoCmd(Arrays.asList(
					new ExtraInfoBlock(ExtraInfoBlock.TYPE_CERTINFO_HASHA,
							new ExtraInfoData(
									ExtraInfoData.FLAG_HASH_PRESENT,
									CertificateInfo.HASHA_DEFAULT)),
									new ExtraInfoBlock(ExtraInfoBlock.TYPE_CERTINFO_HASHB,
											new ExtraInfoData(
													ExtraInfoData.FLAG_HASH_PRESENT,
													CertificateInfo.HASHB_DEFAULT)))));
			request(new MyInfoRequest());

		} else if (cmd instanceof ParamInfoCmd) {
			ParamInfoCmd pic = (ParamInfoCmd) cmd;

			ParamInfo info = pic.getParamInfo();

			request(new SetParamInfoCmd(new ParamInfo(0,
					info.getFlags() | ParamInfo.FLAG_TYPING_NOTIFICATION, 8000,
					info.getMaxSenderWarning(), info.getMaxReceiverWarning(),
					0)));

		} else if (cmd instanceof YourInfoCmd) {
			YourInfoCmd yic = (YourInfoCmd) cmd;

			FullUserInfo info = yic.getUserInfo();


			//System.out.println("icq: got my user info: " + info);

		} else if (cmd instanceof UserInfoCmd) {
			UserInfoCmd uic = (UserInfoCmd) cmd;

			String sn = uic.getUserInfo().getScreenname();

			//System.out.println("icq: user info for " + sn + ": "
			//        + uic.getInfoData());

		} else if (cmd instanceof ServiceRedirect) {
			ServiceRedirect sr = (ServiceRedirect) cmd;

			//            System.out.println("icq: connecting to " + sr.getRedirectHost()
			//                    + " for 0x" + Integer.toHexString(sr.getSnacFamily()));

			icq.connectToService(sr.getSnacFamily(), sr.getRedirectHost(),
					sr.getCookie());

		} else if (cmd instanceof SsiRightsCmd) {
			SsiRightsCmd src = (SsiRightsCmd) cmd;

			int[] maxima = src.getMaxima();

			for (int i = 0; i < maxima.length; i++) {
				int max = maxima[i];
				//                System.out.println("icq: - Max SSI items of type 0x"
				//                        + Integer.toHexString(i) + ": " + max);
			}

		} else if (cmd instanceof SsiDataCmd) {
			SsiDataCmd sdc = (SsiDataCmd) cmd;

			/** read local stored contacts */
			//Reader reader = new Reader();
			//Group storedRootGroup = reader.readContactList(String.valueOf(icq.getUIN()), ProtocolType.ICQ, Controller.getInstance().getAccountActivity());
//			Group storedRootGroup = new Group("/");
//			
//			/** create a fresh new root group and fill w/ contacts received from server */
//		    Group serverRootGroup = new Group("/");

		    
			List<SsiItem> items = sdc.getItems();
			System.out.println("icq: SSI items: " + items.size());
			
			for (SsiItem item : items) {
				SsiItemObj obj = itemFactory.getItemObj(item);
				System.out.println("--> " + (obj == null ? (Object) item
                        : (Object) obj));
				/** build contact list */
                System.out.println("--> " + (obj == null ? (Object) item
                        : (Object) obj));
                
                
				if (item.getItemType() == SsiItem.TYPE_GROUP ) {
					if (obj instanceof RootItem) {
						RootItem ri = (RootItem) obj;
						
						for (int id : ri.getGroupids()) {
							Controller.getInstance().getfServerRootGroup().addSubGroup(new Group(id));
							//serverRootGroup.addSubGroup(new Group(id));
						}		
					}
					else if (obj instanceof GroupItem) {
						GroupItem gi = (GroupItem) obj;
						
						
						Iterator<Group> git = Controller.getInstance().getfServerRootGroup().getSubgroups();
						
						while (git.hasNext()) {
							Group group = (Group) git.next();
							if (group.getGid() == gi.getId() && gi.getBuddies() != null) {
								group.setName(gi.getGroupName());
								group.setfMyGroupItem(gi);
								
								for( int nr : gi.getBuddies()) {
									group.addContact(new Contact(nr, ProtocolType.ICQ));
								}
				
								//show empty groups...
	                		}else if(group.getGid() == gi.getId()){
	                			group.setName(gi.getGroupName());
	                			group.setfMyGroupItem(gi);
	                		}
	                	}
                	}
                }
				
                if (item.getItemType() == SsiItem.TYPE_BUDDY || item.getItemType() == 0x19) {
                	if (obj instanceof BuddyItem ) {
                		BuddyItem bi = (BuddyItem) obj;
                		Iterator<Group> gi = Controller.getInstance().getfServerRootGroup().getSubgroups();
                		while (gi.hasNext()) {

							Group group = (Group) gi.next();
							
							Iterator<Contact> ci = group.getContacts();
							while (ci.hasNext()) {
								Contact contact = (Contact) ci.next();
								if (group.getGid() == bi.getGroupId() && contact.getUid() == bi.getId()) {
									contact.setName(bi.getAlias());
									contact.setUin(bi.getScreenname());
									contact.setMyBuddyItem(bi);
								}
							}
						}
					}
				}
			}

			/** merge stored contact list w/ server list */
		//	Controller.getInstance().mergeContactLists(storedRootGroup, serverRootGroup);
			Controller.getInstance().mergeContactLists();

			//            Iterator<Group> gi = serverRootGroup.getSubgroups();
			//    		while (gi.hasNext()) {
			//				Group group = (Group) gi.next();
			//				Iterator<Contact> ci = group.getContacts();
			//				while (ci.hasNext()) {
			//					Contact contact = (Contact) ci.next();
			//					//if
			//				}
			//    		}



			if (items.size() == 0 || sdc.getLastModDate() != 0) {
				//System.out.println("icq: done with SSI");
				request(new ActivateSsiCmd());
				clientReady();



			}
			//        } else if (cmd instanceof SsiRightsCmd) {
			//            SsiRightsCmd src = (SsiRightsCmd) cmd;
			//
			//            System.out.println("icq: SSI maxima:");
			//            int[] maxima = src.getMaxima();
			//            for (int i = 0; i < maxima.length; i++) {
			//                int max = maxima[i];
			//
			//                System.out.println("icq: - 0x" + Integer.toHexString(i) + ": " + max);
			//            }
		}
	}
}
